<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>钉钉扫码资产登记</title>
    <link rel="shortcut icon" href="/img/ding-logo.png" type="image/x-icon">
    <!-- 引入钉钉 JSAPI -->
    <!-- <script src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"></script> -->
    <script defer src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
    <!-- 引入新版本钉钉 JSAPI -->
    <script defer src="https://g.alicdn.com/dingding/h5-dingtalk-login/0.21.0/ddlogin.js"></script>
</head>
<body>
<!-- 添加一个包裹容器来组织二维码相关的元素 -->
<div class="qr-container" id="normal_ding_container">
    <div class="qr-header">
        <img src="/img/ding-logo.png" class="dingtalk-logo">
        <div class="scan-text">请使用钉钉app扫码</div>
    </div>
    <div id="self_defined_element" class="self-defined-classname"></div>
</div>
<div class="qr-container hidden" id="zhezheng_ding_container">
    <div class="qr-header">
        <img src="/img/ding-logo.png" class="dingtalk-logo">
        <div class="scan-text">请使用浙政钉app扫码</div>
    </div>
    <iframe id="zhezheng_ding_iframe" style="width: 280px; height: 280px; border: none;"></iframe>
</div>
<div id="success_icon" class="success-icon hidden">
    <svg viewBox="0 0 52 52">
        <circle class="success-circle" cx="26" cy="26" r="25" fill="none"/>
        <path class="success-check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/>
    </svg>
</div>
<style>
    html,body {
        margin: 0;
        padding: 0;
        height: 100%;
    }
    /* Message组件样式 */
    .message-container {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        background: rgba(0, 0, 0, 0.7);
        color: white;
        padding: 15px 25px;
        border-radius: 4px;
        z-index: 9999;
        opacity: 0;
        transition: opacity 0.3s ease-in-out;
    }
    .message-container.show {
        opacity: 1;
    }
    .self-defined-classname {
        width: 280px;
        height: 280px;
        position: relative;
        margin: 0 auto;
        line-height: 280px;
        text-align: center;
    }
    .success-icon {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 280px;
        height: 280px;
        background: rgba(255, 255, 255, 0.95);
        border-radius: 0;
        display: flex;
        justify-content: center;
        align-items: center;
        box-sizing: border-box;
        z-index: 1000;
        margin-left: 1px;
        margin-top: 1px;
    }
    .success-icon svg {
        width: 80px;
        height: 80px;
    }
    .success-icon.hidden {
        display: none;
    }
    .success-circle {
        stroke: #4CAF50;
        stroke-width: 2;
        stroke-dasharray: 166;
        stroke-dashoffset: 166;
        animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;
    }
    .success-check {
        stroke: #4CAF50;
        stroke-width: 2;
        stroke-dasharray: 48;
        stroke-dashoffset: 48;
        animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.6s forwards;
    }
    @keyframes stroke {
        100% {
            stroke-dashoffset: 0;
        }
    }
    .qr-container {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        text-align: center;
    }
    .qr-header {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-top: -8px;
        position: absolute;
        width: 100%;
        z-index: 10;
    }
    .dingtalk-logo {
        width: 24px;
        height: 24px;
        margin-right: 8px;
        border-radius: 4px;
    }
    .scan-text {
        font-size: 16px;
        color: #333;
    }
    .hidden {
        display: none;
    }
</style>
<script>
// Message组件
const Message = {
    timer: null,
    container: null,

    createContainer() {
        if (!this.container) {
            this.container = document.createElement('div');
            this.container.className = 'message-container';
            document.body.appendChild(this.container);
        }
        return this.container;
    },

    show(text, duration = 3000) {
        const container = this.createContainer();
        container.textContent = text;
        container.classList.add('show');

        if (this.timer) {
            clearTimeout(this.timer);
        }

        this.timer = setTimeout(() => {
            this.hide();
        }, duration);
    },

    hide() {
        if (this.container) {
            this.container.classList.remove('show');
        }
    }
};
// APIService 类：处理所有的 AJAX 请求
class APIService {
    constructor() {
        this.baseUrl = location.origin;
    }

    async request(options) {
        const defaults = {
            type: 'GET',
            url: '',
            data: null,
            contentType: 'application/x-www-form-urlencoded'
        };
        options = Object.assign({}, defaults, options);

        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            let data = options.data;

            if (data && typeof data === 'object') {
                if (options.contentType === 'application/json') {
                    data = JSON.stringify(data);
                } else {
                    data = Object.keys(data)
                        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
                        .join('&');
                }
            }

            if (options.type.toUpperCase() === 'GET' && data) {
                options.url += (options.url.includes('?') ? '&' : '?') + data;
                data = null;
            }

            xhr.open(options.type, options.url, true);

            if (options.type.toUpperCase() === 'POST') {
                xhr.setRequestHeader('Content-Type', options.contentType);
            }

            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                        let response;
                        try {
                            response = JSON.parse(xhr.responseText);
                        } catch (e) {
                            response = xhr.responseText;
                        }
                        resolve(response);
                    } else {
                        reject(xhr);
                    }
                }
            };

            xhr.send(data);
        });
    }

    async checkRequestId(terminalRequestId) {
        return this.request({
            url: '/flow/terminalPage/checkRequestId',
            type: 'POST',
            contentType: 'application/json',
            data: { terminalRequestId }
        });
    }

    async clearRequestId(terminalRequestId) {
        return this.request({
            url: '/flow/terminalPage/clearRequestId',
            type: 'POST',
            contentType: 'application/json',
            data: { terminalRequestId }
        });
    }

    async registerCallback(code, terminalGuid, tenantId) {
        return this.request({
            url: '/registerCallback/dingTalk',
            data: { code, terminalGuid, tenantId }
        });
    }

    async getImageBase64(fileId) {
        return this.request({
            url: '/file/img/base64',
            type: 'GET',
            data: { fileId }
        });
    }
}

// UIController 类：处理页面显示逻辑
class UIController {
    constructor() {
        this.normalContainer = document.getElementById('normal_ding_container');
        this.zhezhengContainer = document.getElementById('zhezheng_ding_container');
        this.successIcon = document.getElementById('success_icon');
        this.qrContainer = document.getElementById('self_defined_element');
        this.normalScanText = document.querySelector('#normal_ding_container .scan-text');
        this.zhezhengScanText = document.querySelector('#zhezheng_ding_container .scan-text');
        this.dingTalkLogos = document.querySelectorAll('.dingtalk-logo');
    }

    setDingTalkLogo(base64) {
        this.dingTalkLogos.forEach(logo => {
            logo.src = `data:image/png;base64,${base64}`;
        });
    }

    setScanText(text) {
        this.normalScanText.textContent = text;
        this.zhezhengScanText.textContent = text;
    }

    showSuccess() {
        this.successIcon.classList.remove('hidden');
    }

    showError(msg) {
        Message.show(msg)
    }

    setQRContainerContent(content) {
        this.qrContainer.innerHTML = content;
    }

    switchToZhezhengDing() {
        this.normalContainer.classList.add('hidden');
        this.zhezhengContainer.classList.remove('hidden');
    }

    setZhezhengDingUrl(url) {
        document.getElementById('zhezheng_ding_iframe').src = url;
    }
}

// QRCodeManager 类：处理二维码生成和管理
class QRCodeManager {
    constructor(apiService, uiController) {
        this.apiService = apiService;
        this.uiController = uiController;
        this.params = this.getUrlParams();
        this.bindEvents();
    }

    getUrlParams() {
        const params = {};
        ['terminalGuid', 'tenantId', 'terminalRequestId', 'clientId', 'syncType', 'tips', 'logoFileId', 'newApi'].forEach(param => {
            params[param] = this.getUrlParam(param);
        });
        params.clientId = params.clientId || 'dingfib3ysek9jxtlqix';
        params.isZheZhengDing = params.syncType === 'DingTalkGov';
        params.tips = params.tips || '请使用钉钉app扫码';
        params.newApi = params.newApi !== 'false'; // 默认为true，只有明确设置为'false'时才为false
        return params;
    }

    getUrlParam(param) {
        const reg = new RegExp("(^|&)" + param + "=([^&]*)(&|$)");
        const r = window.location.search.substr(1).match(reg);
        return r != null ? decodeURIComponent(r[2]) : null;
    }

    bindEvents() {
        if (this.params.isZheZhengDing) {
            window.addEventListener('message', this.handleZhezhengDingCallback.bind(this));
        }
    }

    async init() {
        this.uiController.setScanText(this.params.tips);
        this.initQRCode();
    }

    initQRCode() {
        if (this.params.isZheZhengDing) {
            this.initZhezhengDing();
        } else {
            if (this.params.newApi) {
                this.generateNewNormalQRCode();
            } else {
                this.generateNormalQRCode();
            }
        }
    }

    handleMessage (event) {
        var origin = event.origin;
        console.log("origin", event.origin);
        if( origin == "https://login.dingtalk.com" ) { //判断是否来自ddLogin扫码事件。
            var loginTmpCode = event.data; 
            //获取到loginTmpCode后就可以在这里构造跳转链接进行跳转了
            console.log("loginTmpCode", loginTmpCode);
            window.location.href = this.gotoUrl + '&loginTmpCode=' + loginTmpCode
            // this.handleCallback(loginTmpCode)
        }
    }

    generateNormalQRCode() {
        var redirect_uri= encodeURIComponent(`http://47.99.79.163:8088/registerCallback/dingTalk?terminalGuid=${this.params.terminalGuid}&tenantId=${this.params.tenantId}`)
        this.gotoUrl = `https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=${this.params.clientId}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=${redirect_uri}`
        window.DDLogin({
            id: "self_defined_element",
            style: "border:none;background-color:#FFFFFF;",
            width: 280,
            height: 320,
            goto: encodeURIComponent(this.gotoUrl)
        })
        if (typeof window.addEventListener != 'undefined') {
            window.addEventListener('message', this.handleMessage.bind(this), false);
        } else if (typeof window.attachEvent != 'undefined') {
            window.attachEvent('onmessage', this.handleMessage.bind(this));
        }
    }

    generateNewNormalQRCode() {
        window.DTFrameLogin({
            id: 'self_defined_element',
            width: 280,
            height: 280,
        },
        {
            redirect_uri: encodeURIComponent(`${location.origin}/registerCallback/dingTalk`),
            client_id: this.params.clientId,
            scope: 'openid',
            response_type: 'code',
            state: 'dddd',
            prompt: 'consent',
        },
        this.handleNormalDingCallback.bind(this),
        this.handleError.bind(this));
    }

    initZhezhengDing() {
        this.uiController.switchToZhezhengDing();
        const zhezhengDingUrl = 'https://login.dg-work.cn/oauth2/auth.htm' +
            '?response_type=code' +
            '&client_id=' + this.params.clientId +
            '&redirect_uri=' + encodeURIComponent(location.origin + `/registerCallback/dingTalk?terminalGuid=${this.params.terminalGuid}&tenantId=${this.params.tenantId}`) +
            '&scope=get_user_info' +
            '&authType=QRCODE' +
            '&embedMode=true';
        this.uiController.setZhezhengDingUrl(zhezhengDingUrl);
    }

    async handleNormalDingCallback(loginResult) {
        const {authCode} = loginResult;
        await this.handleCallback(authCode);
    }

    async handleZhezhengDingCallback(event) {
        if (event.data && event.data.code) {
            await this.handleCallback(event.data.code);
        }
    }

    async handleCallback(code) {
        try {
            const res = await this.apiService.registerCallback(
                code,
                this.params.terminalGuid,
                this.params.tenantId
            );
            if (res.code === 0) {
                this.uiController.showSuccess();
                await this.apiService.clearRequestId(this.params.terminalRequestId);
            } else {
                this.uiController.showError(res.msg);
            }
        } catch (err) {
            console.error(err);
            this.uiController.showError('登记失败');
        }
    }

    handleError(errorMsg) {
        console.error(`errorMsg of errorCbk: ${errorMsg}`);
        this.uiController.showError(errorMsg);
    }
}

// 初始化应用
document.addEventListener('DOMContentLoaded', () => {
    const apiService = new APIService();
    const uiController = new UIController();
    const qrCodeManager = new QRCodeManager(apiService, uiController);
    // 并行执行getImageBase64和init
    apiService.getImageBase64(qrCodeManager.params.logoFileId).then(res => {
        if (res.code === 0 && res.data.base64) {
            uiController.setDingTalkLogo(res.data.base64);
        }
    }).catch(err => {
        uiController.showError('获取钉钉logo失败');
        console.error('获取钉钉logo失败:', err);
    });
    
    qrCodeManager.init();
});
</script>
</body>
</html>
